package com.yc.springmvc.core;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.yc.springmvc.core.annotation.ResponseBody;
import com.yc.springmvc.core.util.StringUtil;

/**
 * 请求分发器
 * @author 谢俊峰
 * @data data
 * @QQ 1575623833
 */
public class DispatcherServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	private String contextConfigLocation = "springmvc.properties";
	private FrameworkCore frameworkCore = null;
	
	@Override
	public void init(ServletConfig config) throws ServletException {
		String temp = config.getInitParameter("contextConfigLocation");
//		System.out.println("temp: " + temp);
		if (!StringUtil.checkNull(temp)) {
			this.contextConfigLocation = temp;
		}
//		System.out.println(this.contextConfigLocation);
		// TODO  开始扫描解析基址路径
		frameworkCore = new FrameworkCore(this.contextConfigLocation);
	}
	
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO 获取请求地址
		String url = req.getRequestURI();
		
		// TODO 获取请求的项目名
		String contextPath = req.getContextPath(); 
//		System.out.println("contextPath -- " + contextPath);
		
		// TODO 获取请求的资源地址
		url = url.replaceFirst(contextPath, "").replaceAll("/+", "/");
		
		// TODO 请求地址中是否有参数
		if (url.contains("?")) {
			url = url.substring(0, url.indexOf("?"));
		}
		
		System.out.println("url2: " + url);
		// TODO 根据请求路径从handlerMapper中获取处理这个请求的方法
		HandlerMapperInfo mapperInfo = frameworkCore.getMapper(url);  ////////////////////////////////////////
		System.out.println("mapperInfo -- " + mapperInfo);
		// TODO 如果有则激活这个方法(要先处理好参数)
		if (mapperInfo == null) {
			HandlerResponse.handleStaticResources(resp, req.getRealPath("") + url.substring(1));
			return;
		}
		
		try {
			// TODO 处理动态资源
			Method method = mapperInfo.getMethod();
			
			// 获取这个方法的形参列表
			Object[] args = HandlerRequest.handle(req, method, resp);
			
			Object result = null;
			if (args == null) {  // 说明没有参数注入
				try {
					result = method.invoke(mapperInfo.getObject(), args);
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			// 处理返回结果  判断这个方法上是否有@ResponseBody 如果有则以json格式返回
			if (method.isAnnotationPresent(ResponseBody.class) || mapperInfo.getObject().getClass().isAnnotationPresent(ResponseBody.class)) {
				HandlerResponse.sendJson(resp, result);
				return;
			}
			
			// 重定向或内部转发
			String path = String.valueOf(result);
			if (path.startsWith("redirect:")) {  // 说明要重定向
				path = path.replaceFirst("redirect:", "").trim();
				if (path.startsWith("/")) {
					path = contextPath + path;
				}
				resp.sendRedirect(path);
				return;
			}
			
			req.getRequestDispatcher(path).forward(req, resp);
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}
	
}
